package com.devframe.web.taglib;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;

import com.devframe.sysbase.loader.SysBaseContainer;


/**
 * 
 * <pre>
 * &lt;b&gt;&lt;font color=&quot;blue&quot;&gt;RadioTag&lt;/font&gt;&lt;/b&gt;
 * </pre>
 * 
 * <pre>
 * &lt;b&gt; --单选按钮生成--&lt;/b&gt;
 * </pre>
 * <pre>
 * 支持array\list\map
 * 支持默认值
 * </pre>
 * <pre>
 * &lt;b&gt;--样例--&lt;/b&gt;
 *   RadioTag obj = new RadioTag();
 *   obj.method();
 * </pre>
 * 
 * JDK版本：JDK1.4
 * 
 * 
 */
public class RadioTag extends AbstractBaseTag {
	/**
     * serialVersionUID
     */
    private static final long serialVersionUID = 5187013551635396726L;

    /** 
	 * 选项列表数据，可以是list,iterator,array,map等类型，可以使用request中的名字或者通过${}获取的对象。从其他对象的属性得到的数据需要使用EL表达式获取
	 * 
	 */
	private Object items = null;

    /**
     * CODE_TYPE:代码类型字典名，一般为代码表名.
     * 用于直接生成代码表选项
     */
    private String codeType = null; 
    /**
     *  选中值，支持EL表达式
     */
    private String value = null; //
	/**
	 *  默认值，支持EL表达式
	 */
	private String defaultValue = null; //

	/**
	 * 用于从对象中获取值，作为option的value
	 */
	private String valueField;// 

	/**
	 * 用于从对象中获取值，作为option的text
	 */
	private String labelField;// 

	/**
	 * input的name，
	 */
	private String name;// 



    /**
     * 条件字段
     */
    private String condField;

    /**
     * 条件值，支持EL表达式
     */
    private Object condValue;
	
	/**
	 * result
	 */
	private StringBuffer result = new StringBuffer();

	// ////////////////////////////////////////////
	/**
	 * 标签处理逻辑，生成option列表
	 * @return SKIP_BODY
	 */
	public int doStartTag() {
		try {
			this.getBodyContent();
            if(codeType!=null){
                items=SysBaseContainer.accessCacheDataHandle().getCodeMap(codeType);
            }
			if (items == null || items.equals("")) {
				return SKIP_BODY;
			}
			Object options = items;
			if (items instanceof String) {
			    options = findAttribute((String) items);
			}
			if (options == null) {
				return SKIP_BODY;
			}
			if(id==null){
			    id = name;
			}

			Object selectValue = null;
			if (value != null && !"".equals(value)) {
                selectValue = pageContext.findAttribute(this.value);
                if (selectValue == null) {
                    selectValue = value;
                }
            } else if (defaultValue != null && !"".equals(defaultValue)) {
				selectValue = pageContext.findAttribute(this.defaultValue);
				if (selectValue == null) {
					selectValue = defaultValue;
				}
			}
			int i = 0;
			if (options instanceof Map) {
				Map map = (Map) options;
				for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
					Map.Entry entry = (Map.Entry) it.next();
					if(!validateCond(entry)){
                        continue;
                    }
					i++;
					Object value = entry.getValue();
					Object key = entry.getKey();
					createOption(selectValue, i, value, key);
				}
			} else if (options instanceof Iterator || options instanceof Collection) {

				Iterator it = null;
				if (options instanceof Iterator) {
					it = (Iterator) options;
				} else {
					it = ((Collection) options).iterator();
				}
				while (it.hasNext()) {
					Object entry = it.next();
                    if(!validateCond(entry)){
                        continue;
                    }
					createOptionByEntry(selectValue, i, entry);
					i++;
				}
			} else if (options.getClass().isArray()) {// 数组

				int length = Array.getLength(options);
				for (int j = 0; j < length; j++) {
					Object entry = Array.get(options, j);
					if(!validateCond(entry)){
                        continue;
                    }
					createOptionByEntry(selectValue, i, entry);
					i++;
				}
			}

			return SKIP_BODY;
		} catch (Exception e) {
			return SKIP_BODY;
		}
	}

	/**
	 * @param selectValue selectValue
	 * @param i i
	 * @param value value
	 * @param key key
	 * @author:
	 */
	private void createOption(Object selectValue, int i, Object value, Object key) {
		result.append("<input name=\"" + name + "\" id=\"" + id + i + "\" type=\"radio\" value=\"").append(key)
				.append("\"");
		if (key.equals(selectValue)) {
			result.append(" checked");
		}
		;
		result.append(" onclick=\"" + this.getOnclick() + "\">").append("<label for=\"" + id + i + "\">").append(value)
				.append("</label>");
	}

	/**
	 * 根据
	 * 
	 * @param selectValue selectValue
	 * @param i i
	 * @param entry entry
	 * @author: 
	 */
	private void createOptionByEntry(Object selectValue, int i, Object entry) {
		Object value;
		Object key;
		if (entry instanceof Map.Entry) {
			value = ((Map.Entry) entry).getValue();
			key = ((Map.Entry) entry).getKey();
		} else {
			if (valueField == null || valueField.equals("")) {
				key = entry.toString();
			} else {
				key = getPropertyValue(valueField, entry);
			}
			if (labelField == null || labelField.equals("")) {
				value = key;
			} else {
				value = getPropertyValue(labelField, entry);
			}
		}
		createOption(selectValue, i, value, key);
	}

	/**
	 * doEndTag
	 * @return EVAL_PAGE
	 * @throws JspException JspException
	 * @see javax.servlet.jsp.tagext.BodyTagSupport#doEndTag()
	 */
	public int doEndTag() throws JspException {
		try {
			JspWriter writer = null;
			try {
				writer = this.getPreviousOut();
			} catch (Exception e1) {
				writer = pageContext.getOut();
			}

			try {
				writer.print(result.toString());
				result = new StringBuffer();
			} catch (Exception e) {
				e.printStackTrace();
			}
			return EVAL_PAGE;
		} catch (Exception e) {
			return EVAL_PAGE;
		}
	}
	
    /**
     * validateCond
     * 
     * @param item
     *            当前对象
     * @return 是否符合条件
     * 
     */
    private boolean validateCond(Object item) {
        if(this.condField==null || "".equals(this.condField)){
            return true;
        }
        if (item != null && !item.getClass().isPrimitive()) {
            Object condFieldValue = getPropertyValue(this.condField, item);
            if (condFieldValue != null && condFieldValue.equals(condValue)) {
                return true;
            }
        }
        return false;
    }  
	
	/**
	 *  release
	 * @see javax.servlet.jsp.tagext.BodyTagSupport#release()
	 */
	public void release() {
	    this.id=null;
	    this.name=null;
	    this.items=null;
	    this.codeType=null;
	    this.labelField=null;
	    this.valueField=null;
	    this.defaultValue=null;
		super.release();
	}

	public Object getItems() {
		return items;
	}

	public void setItems(Object items) {
		this.items = items;
	}

	public void setItems(String items) {
		this.items = items;
	}

	public String getDefaultValue() {
		return defaultValue;
	}

	public void setDefaultValue(String defaultValue) {
		this.defaultValue = defaultValue;
	}

	public String getValueField() {
		return valueField;
	}

	public void setValueField(String valueField) {
		this.valueField = valueField;
	}

	public String getLabelField() {
		return labelField;
	}

	public void setLabelField(String labelField) {
		this.labelField = labelField;
	}

	public StringBuffer getResult() {
		return result;
	}

	public void setResult(StringBuffer result) {
		this.result = result;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}


    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getCodeType() {
        return codeType;
    }

    public void setCodeType(String codeType) {
        this.codeType = codeType;
    }

    public String getCondField() {
        return condField;
    }

    public void setCondField(String condField) {
        this.condField = condField;
    }

    public Object getCondValue() {
        return condValue;
    }

    public void setCondValue(Object condValue) {
        this.condValue = condValue;
    }

}
